package main

import "fmt"

// 1、求n的阶乘。至少使用递归函数完成一次。
func a1(n int) int {
	if n < 1 {
		panic("不能小于1")
	}
	p := 1
	for i := 2; i <= n; i++ {
		p *= i
	}
	return p
}

// func a2(n int) uint64 {
// 	var b int = 1
// 	for i := 1; i <= n; i++ {
// 		b = b * i
// 	}
// 	return uint64(b)
// }

func a2(n, b uint64) uint64 {
	if n == 1 {
		return b
	}
	return a2(n-1, n*b)
}

func a3(n int) int {
	if n < 1 {
		panic("不能小于1")
	} else if n == 1 {
		return 1
	}
	return n * a3(n-1)

}

// 2、编写一个函数，接受一个参数n，n为正整数。要求数字必须对齐
func b1(n int) {
	for i := 0; i < n; i++ { //控制行数
		for j := 0; j < n-i-1; j++ { //打印行前面的空格
			fmt.Printf("%-3v", " ")
		}
		for k := i + 1; k > 0; k-- { //打印行后面的数字
			fmt.Printf("%-3d", k)
		}
		fmt.Println()
	}
}

func b2() {
	width := 40
	var line string

	for i := 1; i < 10; i++ { // 控制行数
		line = ""
		for j := i; j >= 1; j-- { // 控制每行的内容
			// fmt.Print(j, " ")
			line += fmt.Sprint(j) + " "
		}
		fmt.Printf("%[2]*[1]s\n", line, width)
		// fmt.Printf("%[1]*s\n",width,line)
	}
}

// 先计算出最后一行，得到宽度，在循环生成
func b3(n int) {
	last := ""
	for i := n; i >= 1; i-- {
		if i == 1 {
			last += fmt.Sprint(i)
		} else {
			last += fmt.Sprintf("%d ", i)
		}
	}
	width := len(last)
	// fmt.Println(width, last)
	line := ""
	for i := 1; i <= n; i++ {
		line = ""
		for j := i; j >= 1; j-- {
			if j == 1 {
				line += fmt.Sprint(j)
			} else {
				line += fmt.Sprintf("%d ", j)
			}
		}
		fmt.Printf("%[1]*v\n", width, line)
	}
}

// 通过最后一行切片生成，效率最高
func b4(n int) {
	last := ""
	for i := n; i >= 1; i-- {
		if i == 1 {
			last += fmt.Sprint(i)
		} else {
			last += fmt.Sprintf("%d ", i)
		}
	}
	width := len(last)
	for i := width - 1; i >= 0; i-- {
		if last[i] == 32 {
			fmt.Printf("%[1]*v\n", width, last[i:])
		}
	}
	fmt.Println(last)
}

func main() {
	// fmt.Println(a1(3))
	// fmt.Println(a2(uint64(3), uint64(1)))
	// fmt.Println(a3(3))
	// fmt.Println(a1(20))
	// fmt.Println(a2(20, 1))
	// b1(40)
	// b2()
	// b3(40)
	b4(10)
}
